﻿using System;
using System.Collections.Generic;
using System.Linq;
using PicoContainer;
using System.Windows.Input;
using XEvolve.Core.Runtime;
using XEvolve.Core.Runtime.Attributes;

namespace XEvolve.Presentation.Input.Internal
{
    internal class XCommandManager : IStartable
    {
        private readonly IDictionary<string, IList<XCommandBinding>> commandBindings = new Dictionary<string, IList<XCommandBinding>>();
        private readonly IExtensionPoint handlers;

        public XCommandManager([Extensions("xevolve.presentation.command.bindings")] XCommandBinding[] commandBindings,
                               [ExtensionPoint("xevolve.presentation.command.handlers")] IExtensionPoint handlers)
        {
            this.handlers = handlers;
            foreach(var commandBinding in commandBindings)
            {
                if (!this.commandBindings.ContainsKey(commandBinding.Context))
                {
                    this.commandBindings[commandBinding.Context] = new List<XCommandBinding>();
                }
                this.commandBindings[commandBinding.Context].Add(commandBinding);
            }
        }

        private IEnumerable<XCommandBinding> GetBindings(string context)
        {
                if (!commandBindings.ContainsKey(context)) return new XCommandBinding[0];
                var bindings = commandBindings[context];
                foreach (var binding in bindings.Where(b => b.Handler == null))
                {
                    binding.Handler = (ICommandHandler) handlers.GetExtension(binding.HandlerType);
                }
                return bindings.ToArray();
        }

        internal CommandBinding[] GetCommandBindings(string context)
        {
            return GetBindings(context).Select(binding => CreateCommandBinding(binding)).ToArray();
        }

        private static CommandBinding CreateCommandBinding(XCommandBinding binding)
        {
            var handler = new CommandHandler(binding.Handler);
            return new CommandBinding(binding.Command, handler.Execute, handler.CanExecute);
        }

        public void Start()
        {
            CommandBindings.Manager = this;
        }

        public void Stop()
        {
        }
    }
}
